#include <QDateTime>
#include <QtSql>
#include <QDebug>
#include <QInputDialog>
#include <QMessageBox>
#include <QDesktopServices>
#include "dialog.h"
#include "ui_dialog.h"
#include "macro.h"
#include "Tcp/aTcpServer.h"
#include "statusoperation.h"
#include "P2P/p2ppeer.h"
#include "P2P/threadpeer.h"
#include "P2P/p2pserver.h"
#include "ONSClient/onsmessenger.h"
#include "DBO/dbointhread.h"
#include "DBO/protocal.h"
#include "eventop.h"
#include "WebServer/webserverconfigdialog.h"
#include "ui_webserverconfigdialog.h"
#include "DBO/datamining.h"
#include "WebServer/webserver.h"
#include "WriteLog/threadWriteLog.h"
#include "Processes/threadprocess.h"
#include "Adapters/adapters.h"
#include "Adapters/AdapterTelnet/AdapterTelnet.h"
#include "ThreadSensorData/threadsensordata.h"
#include "SyncDataBase/dialogsyncdatabase.h"
#include "ThreadClient/clientDataProcess.h"
#include "Agent/agentinthread.h"

WeatherStation::WeatherStation(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::weatherStation)
{

    ui->setupUi(this);
    myP2pServer=NULL; p2PPeer=NULL;
    curntThreadPeerID=0;

    statusOperation=NULL;
    threadDBORelated=NULL;
    threadOfWebServer=NULL;

    udpSocket=new QUdpSocket(this);
    udpSocketForGW=new QUdpSocket(this);


    slotShowErrorInfo(tr("正在启动Agent模块......"));
    agentInThread=new AgentInThread();
    threadAgent=new QThread(this);
    connect(threadAgent,SIGNAL(finished()),agentInThread,SLOT(deleteLater()));
    connect(this,SIGNAL(sigPacketToAgent(QByteArray,QString,quint16)),
            agentInThread,SLOT(slotPacketToAgent(QByteArray,QString,quint16)));
    connect(agentInThread,SIGNAL(sigSendDataToApp(QByteArray,QString,quint16)),
            this,SLOT(slotSendPacket2App(QByteArray,QString,quint16)));
    connect(agentInThread,SIGNAL(sigErrorInfo(QByteArray)),this,SLOT(slotShowErrorInfo(QByteArray)));
    connect(agentInThread,SIGNAL(sigSetIPAnalyzeIncomeDatagram(QByteArray,QHostAddress,quint16)),
            this,SLOT(slotSetIPAnalyzeIncomeDatagram(QByteArray,QHostAddress,quint16)));
    agentInThread->moveToThread(threadAgent);
    threadAgent->start(QThread::LowPriority);


    /********数据库操作******************/
    dbo=new DatabaseOperation(this);
    if(!dbo->createConnection(DB_NAME,DB_HOST,DB_USERNAME,DB_PWD,DB_CON_NAME_WEATHERSTATION))
    {
        QMessageBox::critical(this,tr("连接数据库失败"),"connection "DB_CON_NAME_WEATHERSTATION" failed:"
                              +dbo->query->lastError().text());
       exit(10);
    }
    else
      slotShowErrorInfo(QStringLiteral("Connection "DB_CON_NAME_WEATHERSTATION" successful"));
    connect(dbo,SIGNAL(sigErrorInfo(QString)),this,SLOT(slotShowErrorInfo(QString)));

    /****************数据库操作结束***********/
    statusOperation=new StatusOperation(this);
    qApp->processEvents(QEventLoop::AllEvents,MAX_ProcessEvents_MiliSecs);

    slotShowErrorInfo(tr("正在启动P2P模块......"));
    myP2pServer=new P2PServer(this); //p2pServer需要在udpSocket初始化之后才初始化
    qApp->processEvents(QEventLoop::AllEvents,MAX_ProcessEvents_MiliSecs);

     p2PPeer=new P2PPeer(this);
     p2PPeer->setUdpSocket(udpSocket);//初始化p2PPeer的udpSocket

    hashCmdAckStatusIDMeaning->insert(1,"1:OK");
    hashCmdAckStatusIDMeaning->insert(2,"2:Failure In Cmd Execution");
    hashCmdAckStatusIDMeaning->insert(3,"3:Node Not Found");
    hashCmdAckStatusIDMeaning->insert(4,"4:Bad Request");
    hashCmdAckStatusIDMeaning->insert(5,"5:No Reponse");
    hashCmdAckStatusIDMeaning->insert(6,"6:Bad Request");
    hashCmdAckStatusIDMeaning->insert(7,"7:Not Implementd");


    this->setWindowFlags(Qt::Window);
    isInternetIPchanged=false;
    isUdpOK=true;isUdpGWOK=true;

    threadWriteLog=new ThreadWriteLog(this);
    threadWriteLog->start();
    connect(this,SIGNAL(sigWriteLog(QByteArray)),threadWriteLog,SIGNAL(sigWriteLog(QByteArray)));


    myTcpServer.setParent(this);
    if(!myTcpServer.listen(QHostAddress::Any,tcpServerPort)) //使用指定的aServerIP，而非QHostAddress::anyAddress,可以避免一些问题
        qDebug()<<"1Failed to listen "+myTcpServer.errorString();
    myTcpServerSend.setParent(this);
    if(!myTcpServerSend.listen(QHostAddress::Any,tcpServerPortS))
        qDebug()<<"Failed to listen "+myTcpServerSend.errorString();
    connect(&myTcpServer,SIGNAL(sigErrorInfo(QString)),this,SLOT(slotShowErrorInfo(QString)));
    connect(&myTcpServerSend,SIGNAL(sigErrorInfo(QString)),this,SLOT(slotShowErrorInfo(QString)));

    webServerConfDlog=new WebServerConfigDialog(this);

#ifdef EnableWebServer
    if(webServerConfDlog->exec()==Rejected)
            exit(11); //退出程序
#endif

    slotShowErrorInfo(tr("启动中，请耐心等待.........."));
    show();

    QTimer::singleShot(500,this,SLOT(slotInitStepOne()));
}

void WeatherStation::slotInitStepOne()
{

    slotShowErrorInfo(tr("正在进行第一步初始化，请耐心等待......"));
    clientDataProcess=new ClientDataProcess();
    threadClient=new QThread(this);
    connect(this,SIGNAL(sigProcessClientData(QByteArray,QByteArray,quint16)),clientDataProcess,
            SLOT(slotProcessClientData(QByteArray,QByteArray,quint16)));
    connect(clientDataProcess,SIGNAL(sigClientDataProcessDone(QByteArray,QByteArray,quint16)),this,
            SLOT(slotClientDataProcessDone(QByteArray,QByteArray,quint16)));
    connect(threadClient,SIGNAL(finished()),clientDataProcess,SLOT(deleteLater()));
    connect(threadClient,SIGNAL(started()),clientDataProcess,SLOT(slotConnectDB()));
    connect(clientDataProcess,SIGNAL(sigErrorInfo(QString)),this,SLOT(slotShowErrorInfo(QString)));

    clientDataProcess->moveToThread(threadClient);
    threadClient->start();

    QTimer::singleShot(300,this,SLOT(slotInitStepTwo()));
}

void WeatherStation::slotInitStepTwo()
{
    slotShowErrorInfo(tr("正在进行第二步初始化，请耐心等待......"));

    dboInThread=new DBOInThread();
    threadDBORelated=new QThread(this);
    connect(threadDBORelated,SIGNAL(finished()),dboInThread,SLOT(deleteLater()));
    connect(threadDBORelated,SIGNAL(started()),dboInThread,SLOT(slotConnectDB()));
    if(threadDBORelated&&statusOperation&&myP2pServer&&dbo) //请保证这一条件
    {
        connect(dboInThread,SIGNAL(sigDeleteNode(qint64,QByteArray)),statusOperation,SIGNAL(sigDeleteNode(qint64,QByteArray)));

        connect(statusOperation,SIGNAL(sigRemoveOneInControllingMacList(QString)),
                dboInThread,SLOT(slotRemoveOneInControllingMacList(QString)));
        connect(this,SIGNAL(sigConvProto(QByteArray,QString,quint16,qint64)),dboInThread,
                SLOT(slotConvertProtocol(QByteArray,QString,quint16,qint64)));
        connect(this,SIGNAL(sigCmdAck(QByteArray)),dboInThread,SLOT(slotCmdAck(QByteArray)));

        connect(dboInThread,SIGNAL(sigDataConvertedForGW(QByteArray,QString,quint16,qint64,QByteArray)),
                this,SLOT(slotProcessConvtedData(QByteArray,QString,quint16,qint64,QByteArray)));
        connect(dboInThread,SIGNAL(sigCmdAckToApp(QByteArray,QString,quint16)),this,SLOT(slotCmdAckToApp(QByteArray,QString,quint16)));

        connect(this,SIGNAL(sigStoreVideo(QByteArray,qint64,quint8,QList <QString>*,QString *,QList <qint64>*)),
           dboInThread,SLOT(slotStoreVideo(QByteArray,qint64,quint8,QList <QString>*,
                                                             QString*,QList <qint64>*)));

        connect(dboInThread,SIGNAL(sigErrorInfo(QString)),this,SLOT(slotShowErrorInfo(QString)));


        connect(statusOperation,SIGNAL(sigRegNode(qint64,QByteArray,qint8,QByteArray,quint16,QByteArray,QByteArray,qint8)),
                dboInThread,SLOT(slotRegNode(qint64,QByteArray,qint8,QByteArray,quint16,QByteArray,QByteArray,qint8)));
        connect(statusOperation,SIGNAL(sigUnRegNode(qint64)),dboInThread,SLOT(slotUnRegNode(qint64)));

        connect(statusOperation,SIGNAL(sigRegSensor(qint64,qint16,qint8)),dboInThread,
                SLOT(slotRegSensor(qint64,qint16,qint8)));
        connect(statusOperation,SIGNAL(sigUnRegSensor(qint64,qint16,qint8)),dboInThread,
                SLOT(slotUnRegSensor(qint64,qint16,qint8)));

        connect(statusOperation,SIGNAL(sigQueryPin(qint64)),dboInThread,
                SLOT(slotPinQuery(qint64)));

        connect(dboInThread,SIGNAL(sigAddVideoSource(QString,quint16,qint64,quint8)),myP2pServer,
                SLOT(addVideoSource(QString,quint16,qint64,quint8)));

        connect(dboInThread,SIGNAL(sigSendONSMesg(QString,QString,QString,QString,QString,QString)),this,
                SLOT(slotSendONSMesg(QString,QString,QString,QString,QString,QString)));
        connect(dboInThread,SIGNAL(sigPinQueryFromNodeDone(QByteArray,qint64)),this,
                SLOT(slotSendToNode(QByteArray,qint64)));

        connect(this,SIGNAL(sigRegSensor(qint64,qint16,qint8)),dboInThread,SLOT(slotRegSensor(qint64,qint16,qint8)));
    }
    dboInThread->moveToThread(threadDBORelated);
    threadDBORelated->start();
    QTimer::singleShot(300,this,SLOT(slotInitStepThree()));
}

void WeatherStation::slotInitStepThree()
{
    slotShowErrorInfo(tr("正在进行第三步初始化，请耐心等待......"));
    slotShowErrorInfo(tr("正在启动WebServer，请耐心等待......"));

    webServer=new WebServer(webServerConfDlog->ui->comboBoxPort->currentText().toUInt(),webServerConfDlog->ui->comboBoxDefaultPage->currentText(),
                            webServerConfDlog->ui->spinBoxUpdateInterval->value(),webServerConfDlog->ui->spinBoxUpdateIntervalPic->value());
    threadOfWebServer=new QThread(this);

    connect(webServer,SIGNAL(sigErrorInfo(QString)),this,SLOT(slotShowErrorInfo(QString)));
#ifdef EnableWebServer

    connect(threadOfWebServer,SIGNAL(started()),webServer,SLOT(slotConnectDB()));
    if(threadOfWebServer&&webServer&&statusOperation) //请保证这一条件
    {
        connect(webServer,SIGNAL(sigMsgBox(QString,QString)),this,SLOT(slotMsgBox(QString,QString)));

        connect(statusOperation,SIGNAL(sigRegSensor(qint64,qint16,qint8)),webServer,
                SLOT(slotAddSensor(qint64,qint16)));
        connect(this,SIGNAL(sigRegSensor(qint64,qint16,qint8)),webServer,
                SLOT(slotAddSensor(qint64,qint16)));

        connect(statusOperation,SIGNAL(sigDeleteNode(qint64,QByteArray)),webServer,
                SLOT(slotDeleteNode(qint64,QByteArray)));

        if(threadDBORelated&&dboInThread) //请保证这一条件
        {
            connect(dboInThread,SIGNAL(sigAddNode(qint64,QByteArray)),
                    webServer,SLOT(slotAddNode(qint64,QByteArray)));
            connect(webServer,SIGNAL(sigRegSensor(qint64,qint16,qint8)),dboInThread,
                    SLOT(slotRegSensor(qint64,qint16,qint8)));
        }
     }

    webServer->moveToThread(threadOfWebServer);
    threadOfWebServer->start(QThread::LowPriority);
    slotShowErrorInfo(tr("Web服务器启动成功......"));

#endif


    //初始化，如果不初始化clientIp,而server主动先发消息，则以后server将不再能够收到消息
    clientIP="255.255.255.255"; clientPort=0;

     slotShowErrorInfo(tr("正在启动数据库存储线程......"));

    QTimer::singleShot(300,this,SLOT(slotInitStepFour()));

}

void WeatherStation::slotInitStepFour()
{
    slotShowErrorInfo(tr("正在进行第四步初始化，请耐心等待......"));

    slotShowErrorInfo(tr("正在启动事件处理模块......"));

    eventOP=new EventOP(udpSocket,this);
    connect(eventOP,SIGNAL(sigInfo(QString)),this,SLOT(slotApdTxt(QString)));

    timerForUpdateONS=new QTimer(this);
    timerForUpdateONS->start(MSForUpdataONS);
    connect(timerForUpdateONS,SIGNAL(timeout()),this,SLOT(slotRegMeToONS()));


    //不要以shareaddress的方式来bind。如果多个线程都bind到相同端口，
    //则只会有一个线程会有readyread信号
    if(!udpSocket->bind(QHostAddress::Any, aServerPort))
    //if(!udpSocket->bind(aServerPort))
        ui->receivedPlainTextEdit->appendPlainText("UdpSocket bind fail"+udpSocket->errorString());
    if (udpSocketForGW->bind(QHostAddress::Any, serverPortForGW))
        ui->receivedPlainTextEdit->appendPlainText("UdpSocketGW bind successfully");
    else
        ui->receivedPlainTextEdit->appendPlainText("UdpSocketGW bind fail"+udpSocketForGW->errorString());

    connect(udpSocketForGW,SIGNAL(readyRead()),
            this,SLOT(processGWDatagrams()));
    connect(udpSocket,SIGNAL(readyRead()),
            this,SLOT(processPendingDatagrams()));
    QByteArray d;
    udpSocket->readDatagram(d.data(),0);
    udpSocketForGW->readDatagram(d.data(),0);

    onsMesger=new ONSMessenger(MY_URI,this);
    slotRegMeToONS();

    timerForInternetHeart=new QTimer(this);
    timerForInternetHeart->start(heartInternetInterval);
    connect(timerForInternetHeart,SIGNAL(timeout()),this,SLOT(slotTimerEventForInternetHeart()));
    QTimer::singleShot(300,this,SLOT(slotInitStepFive()));

}

void WeatherStation::slotInitStepFive()
{
    slotShowErrorInfo(tr("正在进行第五步初始化——启动Adapters，请耐心等待......"));
    adapters=new Adapters(this);
    connectApdatersSigSlots(); //连接adapter的信号与槽
    threadSensorData=new ThreadSensorData(this);
    threadSensorData->start(QThread::NormalPriority);
    connect(this,SIGNAL(sigProcessSensorData(QByteArray,QHostAddress,quint16)),
            threadSensorData,SIGNAL(sigProcessSensorData(QByteArray,QHostAddress,quint16)));
    connect(threadSensorData,SIGNAL(sigEventNotify(QByteArray,QString,quint16)),eventOP,SLOT(processEvent(QByteArray,QString,quint16)));
    connect(threadSensorData,SIGNAL(sigInfo(QString)),this,SLOT(slotApdTxt(QString)));
    connect(threadSensorData,SIGNAL(sigError(QString)),this,SLOT(slotShowErrorInfo(QString)));
    connect(threadSensorData,SIGNAL(sigPacketNodeToServer(QByteArray,QHostAddress,quint16,bool)),
            this,SLOT(analyzeGWDatagram(QByteArray,QHostAddress,quint16,bool)));

    dialogSyncDB=new DialogSyncDataBase(this);

    slotShowErrorInfo(tr("系统启动完成！"));

}

void WeatherStation::slotInitStepSix()
{

}
